﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;

namespace Sgr.Oss.Services
{
    internal class BucketCache
    {
        private readonly ConcurrentDictionary<string, BucketCacheItem> _cache = new();
        private readonly TimeSpan _expiration;

        public BucketCache(TimeSpan expiration)
        {
            _expiration = expiration;
        }

        public bool TryGet(string bucketName, out bool exists)
        {
            exists = false;

            if (string.IsNullOrEmpty(bucketName))
            {
                return false;
            }

            if (_cache.TryGetValue(bucketName, out var item))
            {
                if (!IsExpired(item))
                {
                    exists = item.Exists;
                    return true;
                }
                // 如果已过期，移除该项
                _cache.TryRemove(bucketName, out _);
            }
            return false;
        }

        public void Set(string bucketName, bool exists)
        {
            if (string.IsNullOrEmpty(bucketName))
            {
                return;
            }

            var item = new BucketCacheItem(exists, DateTime.UtcNow);
            _cache.AddOrUpdate(bucketName, item, (_, _) => item);
        }

        public void Remove(string bucketName)
        {
            if (!string.IsNullOrEmpty(bucketName))
            {
                _cache.TryRemove(bucketName, out _);
            }
        }

        public void UpdateAll(IEnumerable<string> existingBuckets)
        {
            if (existingBuckets == null)
            {
                return;
            }

            var bucketSet = new HashSet<string>(existingBuckets, StringComparer.OrdinalIgnoreCase);
            var now = DateTime.UtcNow;

            // 创建要更新的项
            var updates = bucketSet.ToDictionary(
                bucket => bucket,
                _ => new BucketCacheItem(true, now),
                StringComparer.OrdinalIgnoreCase
            );

            // 原子性地更新缓存
            foreach (var update in updates)
            {
                _cache.AddOrUpdate(update.Key, update.Value, (_, _) => update.Value);
            }

            // 移除不存在的存储桶
            var keysToRemove = _cache.Keys
                .Where(k => !bucketSet.Contains(k))
                .ToList();

            foreach (var key in keysToRemove)
            {
                _cache.TryRemove(key, out _);
            }
        }

        private bool IsExpired(BucketCacheItem item)
        {
            return (DateTime.UtcNow - item.LastChecked) >= _expiration;
        }
    }

    internal class BucketCacheItem
    {
        public BucketCacheItem(bool exists, DateTime lastChecked)
        {
            Exists = exists;
            LastChecked = lastChecked;
        }

        public bool Exists { get; }
        public DateTime LastChecked { get; }
    }
}